package com.points.system.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.points.system.domain.PointsOperationLog;
import com.points.system.domain.UserPoints;
import com.points.system.service.PointsOperationLogService;
import com.points.system.service.UserPointsService;
import lombok.RequiredArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 用户积分管理控制器
 */
@RestController
@RequestMapping("/api/points")
@RequiredArgsConstructor
public class UserPointsController {

    private final UserPointsService userPointsService;
    private final PointsOperationLogService pointsOperationLogService;

    /**
     * 查询用户积分信息
     *
     * @param userId 用户ID
     * @return 用户积分信息
     * @apiNote GET /api/points/{userId}
     */
    @GetMapping("/{userId}")
    public UserPoints getUserPoints(@PathVariable Long userId) {
        return userPointsService.getUserPoints(userId);
    }

    /**
     * 为用户充值积分
     *
     * @param userId 用户ID
     * @param points 充值积分数量
     * @param expireTime 积分过期时间（可选）
     * @apiNote POST /api/points/recharge/{userId}?points=100&expireTime=2024-12-31T23:59:59
     */
    @PostMapping("/recharge/{userId}")
    public void rechargePoints(
            @PathVariable Long userId,
            @RequestParam Long points,
            @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime expireTime) {
        userPointsService.rechargePoints(userId, points, expireTime);
    }

    /**
     * 用户消费积分
     *
     * @param userId 用户ID
     * @param points 消费积分数量
     * @apiNote POST /api/points/consume/{userId}?points=50
     * @throws RuntimeException 当用户积分不足时抛出异常
     */
    @PostMapping("/consume/{userId}")
    public void consumePoints(
            @PathVariable Long userId,
            @RequestParam Long points) {
        userPointsService.consumePoints(userId, points);
    }

    /**
     * 批量为用户充值积分
     *
     * @param request 请求体，包含：
     *               - userIds: 用户ID列表
     *               - points: 充值积分数量
     *               - expireTime: 积分过期时间（可选）
     * @apiNote POST /api/points/batch/recharge
     * @example 
     * {
     *   "userIds": [1, 2, 3],
     *   "points": 100,
     *   "expireTime": "2024-12-31T23:59:59"
     * }
     */
    @PostMapping("/batch/recharge")
    public void batchRechargePoints(
            @RequestBody Map<String, Object> request) {
        @SuppressWarnings("unchecked")
        List<Integer> userIdsInt = (List<Integer>) request.get("userIds");
        List<Long> userIds = userIdsInt.stream()
                .map(Long::valueOf)
                .collect(Collectors.toList());
        Long points = Long.valueOf(request.get("points").toString());
        LocalDateTime expireTime = request.get("expireTime") != null ?
                LocalDateTime.parse(request.get("expireTime").toString()) : null;
        userPointsService.batchRechargePoints(userIds, points, expireTime);
    }

    /**
     * 批量消费用户积分
     *
     * @param request 请求体，包含：
     *               - userIds: 用户ID列表
     *               - points: 消费积分数量
     * @apiNote POST /api/points/batch/consume
     * @example
     * {
     *   "userIds": [1, 2, 3],
     *   "points": 50
     * }
     * @throws RuntimeException 当任一用户积分不足时抛出异常
     */
    @PostMapping("/batch/consume")
    public void batchConsumePoints(
            @RequestBody Map<String, Object> request) {
        @SuppressWarnings("unchecked")
        List<Long> userIds = (List<Long>) request.get("userIds");
        Long points = Long.valueOf(request.get("points").toString());
        userPointsService.batchConsumePoints(userIds, points);
    }

    /**
     * 查询用户积分操作日志
     *
     * @param userId 用户ID
     * @param pageNum 页码，默认1
     * @param pageSize 每页记录数，默认10
     * @return 分页的积分操作日志记录
     * @apiNote GET /api/points/logs/{userId}?pageNum=1&pageSize=10
     */
    @GetMapping("/logs/{userId}")
    public IPage<PointsOperationLog> getUserPointsLogs(
            @PathVariable Long userId,
            @RequestParam(defaultValue = "1") Integer pageNum,
            @RequestParam(defaultValue = "10") Integer pageSize) {
        return pointsOperationLogService.getUserPointsLogs(userId, pageNum, pageSize);
    }
} 